import BankingTaskManagement.BankingService;
import RestaurantManagement.RestaurantService;
import ShapeService.ShapeService;
import ShapeService.bouncebox.BounceBox;
import ShapeService.bouncebox.Square;
import ShapeService.bouncebox.Rectangle;
import ZooManagement.Zoo;
import ZooManagement.ZooManager;
import ZooManagement.Animal;
import ShapeService.bounceboxframework.Shape;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.List;

import com.formdev.flatlaf.FlatIntelliJLaf;

public class IMS_Swing_Dashboard extends JFrame {
    // Module panel container (using CardLayout for switching)
    private final JPanel mainPanel = new JPanel(new CardLayout());
    private final CardLayout cardLayout = (CardLayout) mainPanel.getLayout();

    // Initialize currency formatter
    DecimalFormat currencyFormat = new DecimalFormat("RMB #,##0.00");

    // Account Creation Panel Components
    JTextField accountNumberField;
    JTextField initialBalanceField;
    JTextField interestRateField;
    // Transaction Panel Components
    JTextField transactionAccountField;
    JTextField transactionAmountField;
    JComboBox<String> transactionTypeCombo;
    // Task List Components
    DefaultListModel<String> highPriorityModel;
    DefaultListModel<String> lowPriorityModel;
    JList<String> highPriorityList;
    JList<String> lowPriorityList;
    JTextField taskInputField;

    RestaurantService RestaurantService = new RestaurantService();

    ZooManager zooManager = new ZooManager();

    ShapeService shapeService = new ShapeService();

    BankingService bankingService = new BankingService();

    private ArrayList<Shape> currentShapes;  // Stores parsed shape data

    public IMS_Swing_Dashboard() {
        // Initialize FlatLaf theme
        FlatIntelliJLaf.setup();

        // The basic setup for the JFrame window
        setTitle("IMS Swing Dashboard");
        setSize(900, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        // Create the navigation panel with buttons for each module
        JPanel navPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
        JButton zooBtn = new JButton("ZooManagement");
        JButton restaurantBtn = new JButton("RestaurantManagement");
        JButton bankBtn = new JButton("BankingManagement");
        JButton shapeBtn = new JButton("ShapeService");

        // Add navigation button click event (to switch module panels)
        zooBtn.addActionListener(e -> cardLayout.show(mainPanel, "zoo"));
        restaurantBtn.addActionListener(e -> cardLayout.show(mainPanel, "restaurant"));
        bankBtn.addActionListener(e -> cardLayout.show(mainPanel, "bank"));
        shapeBtn.addActionListener(e -> cardLayout.show(mainPanel, "shape"));
        navPanel.add(zooBtn);
        navPanel.add(restaurantBtn);
        navPanel.add(bankBtn);
        navPanel.add(shapeBtn);

        // Add operation panels for each module to the main container
        mainPanel.add(createZooPanel(), "zoo");
        mainPanel.add(createRestaurantPanel(), "restaurant");
        mainPanel.add(createBankPanel(), "bank");
        mainPanel.add(createShapePanel(), "shape");

        // Overall layout (navigation panel at the top, main content in the center)
        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(navPanel, BorderLayout.NORTH);
        getContentPane().add(mainPanel, BorderLayout.CENTER);

    }

    // Zoo Management Module Panel
    private JPanel createZooPanel() {
        Zoo southZoo = new Zoo("SouthZoo");
        Zoo northZoo = new Zoo("NorthZoo");
        zooManager.zooMap.put("SouthZoo", southZoo);
        zooManager.zooMap.put("NorthZoo", northZoo);

        bankingService.createAccount("SouthZoo", 1000);
        bankingService.createAccount("NorthZoo", 1000);

        zooManager.addAnimal("SouthZoo", new Animal("Simba", "African Lion", 6));
        zooManager.addAnimal("SouthZoo", new Animal("Dumbo", "African Elephant", 12));
        zooManager.addAnimal("SouthZoo", new Animal("Luna", "Gray Wolf", 4));
        zooManager.addAnimal("SouthZoo", new Animal("Poe", "Raven", 3));
        zooManager.addAnimal("SouthZoo", new Animal("Benny", "Grizzly Bear", 8));

        zooManager.addAnimal("NorthZoo", new Animal("Arctic", "Polar Bear", 7));
        zooManager.addAnimal("NorthZoo", new Animal("Blizzard", "Snow Leopard", 5));
        zooManager.addAnimal("NorthZoo", new Animal("Frost", "Arctic Fox", 3));
        zooManager.addAnimal("NorthZoo", new Animal("Penguin", "Emperor Penguin", 4));
        zooManager.addAnimal("NorthZoo", new Animal("Aurora", "Caribou", 6));

        JPanel zooPanel = new JPanel(new BorderLayout(10, 10));
        zooPanel.setBorder(BorderFactory.createTitledBorder("Zoo Management"));

        // Add animal panel
        JPanel addAnimalPanel = new JPanel(new FlowLayout());
        addAnimalPanel.setBorder(BorderFactory.createTitledBorder("Add Animal"));

        String[] zooNames = new String[]{"SouthZoo", "NorthZoo"};
        JComboBox<String> zooNameAddField = new JComboBox<>(zooNames);
        JComboBox<String> zooNameDelField = new JComboBox<>(zooNames);
        JComboBox<String> fromZooField = new JComboBox<>(zooNames);
        JComboBox<String> toZooField = new JComboBox<>(zooNames);
        JComboBox<String> zooNameSearchField = new JComboBox<>(zooNames);
        JComboBox<String> zooNameListField = new JComboBox<>(zooNames);
        JComboBox<String> zooNameTicketField = new JComboBox<>(zooNames);

        JTextField animalNameField = new JTextField(10);
        JTextField animalTypeField = new JTextField(10);
        JTextField animalAgeField = new JTextField(5);
        JButton addAnimalBtn = new JButton("Add Animal");

        addAnimalBtn.addActionListener(e -> {
            try {
                String name = animalNameField.getText().trim();
                String type = animalTypeField.getText().trim();
                String ageStr = animalAgeField.getText().trim();

                if (name.isEmpty()) {
                    JOptionPane.showMessageDialog(this, "Animal Name Can Not Be Empty!", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                if (type.isEmpty()) {
                    JOptionPane.showMessageDialog(this, "Animal Type Can Not Be Empty!", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                if (ageStr.isEmpty()) {
                    JOptionPane.showMessageDialog(this, "Animal Name Can Not Be Empty!", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }
                int age = Integer.parseInt(ageStr);
                if (age <= 0) {
                    throw new NumberFormatException("The age must be above 0!");
                }

                zooManager.addAnimal((String) zooNameAddField.getSelectedItem(), new Animal(name, type, age));

                JOptionPane.showMessageDialog(this,
                        "Animal Added Successfully!\nZoo: "
                                + zooNameAddField.getSelectedItem()
                                + "\nName: " + name
                                + "\nType: " + type
                                + "\nAge: " + age,
                        "Success", JOptionPane.INFORMATION_MESSAGE);
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(this, "Age must be a valid number!", "Error", JOptionPane.ERROR_MESSAGE);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Add Animal Failed: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        addAnimalPanel.add(new JLabel("Zoo Name:"));
        addAnimalPanel.add(zooNameAddField);
        addAnimalPanel.add(new JLabel("Animal Name:"));
        addAnimalPanel.add(animalNameField);
        addAnimalPanel.add(new JLabel("Type:"));
        addAnimalPanel.add(animalTypeField);
        addAnimalPanel.add(new JLabel("Age:"));
        addAnimalPanel.add(animalAgeField);
        addAnimalPanel.add(addAnimalBtn);

        // Operate animal panel
        JPanel operationPanel = new JPanel(new FlowLayout());
        operationPanel.setBorder(BorderFactory.createTitledBorder("Animal Operations"));
        JPanel delPanel = new JPanel(new FlowLayout());
        JPanel movePanel = new JPanel(new FlowLayout());

        // Delete animal components
        JTextField delAnimalNameField = new JTextField(10);
        JButton delAnimalBtn = new JButton("Delete Animal");
        delAnimalBtn.addActionListener(e -> {
            String animalName = delAnimalNameField.getText().trim();
            if (zooNameDelField.getSelectedItem() == null || animalName.isEmpty()) {
                JOptionPane.showMessageDialog(this, "Please fill in all fields!", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            zooManager.deleteAnimal((String) zooNameDelField.getSelectedItem(), animalName);
            JOptionPane.showMessageDialog(this, "Animal Removed Successfully!", "Success", JOptionPane.INFORMATION_MESSAGE);
        });

        // Move animal components
        JTextField moveAnimalNameField = new JTextField(10);
        JButton moveAnimalBtn = new JButton("Move Animal");
        moveAnimalBtn.addActionListener(e -> {
            try {
                String from = (String) fromZooField.getSelectedItem();
                String to = (String) toZooField.getSelectedItem();
                String animalName = moveAnimalNameField.getText().trim();

                // Withdraw from the original zoo
                double transportCost = zooManager.getTransportCost(zooManager.zooMap.get(from));  // 原动物园的运输费用
                boolean withdrawSuccess = bankingService.withdraw(from, transportCost);
                if (!withdrawSuccess) {
                    JOptionPane.showMessageDialog(this, "The zoo account does not have enough balance! Can't pay for transport cost!", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                boolean success = zooManager.moveAnimal(from, to, animalName);
                if (success) {
                    JOptionPane.showMessageDialog(this,
                            "Animal Moved Successfully!\nAnimal: " + animalName
                                    + "\nTransportCost: " + zooManager.getTransportCost(zooManager.zooMap.get(to)), "Success", JOptionPane.INFORMATION_MESSAGE);
                } else {
                    JOptionPane.showMessageDialog(this, "Move Failed: Animal Not Found or Two Same Zoos Chosen!", "Error", JOptionPane.ERROR_MESSAGE);
                }
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Move Failed: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        // Assemble operation panel
        delPanel.add(new JLabel("Zoo Name:"));
        delPanel.add(zooNameDelField);
        delPanel.add(new JLabel("Animal Name:"));
        delPanel.add(delAnimalNameField);
        delPanel.add(delAnimalBtn);

        movePanel.add(new JLabel("Zoo (From):"));
        movePanel.add(fromZooField);
        movePanel.add(new JLabel("Zoo (To):"));
        movePanel.add(toZooField);
        movePanel.add(new JLabel("Animal Name:"));
        movePanel.add(moveAnimalNameField);
        movePanel.add(moveAnimalBtn);

        operationPanel.add(delPanel);
        operationPanel.add(movePanel);

        // View animal panel
        JPanel viewPanel = new JPanel(new BorderLayout());
        viewPanel.setBorder(BorderFactory.createTitledBorder("View Animals & Ticket Sales"));

        // List animal components
        JPanel listPanel = new JPanel(new FlowLayout());
        JButton listBtn = new JButton("List Animals");
        listBtn.addActionListener(e -> {
            String zooName = (String) zooNameListField.getSelectedItem();
            ArrayList<Animal> animals = zooManager.listAnimals(zooName);

            if (animals == null || animals.isEmpty()) {
                JOptionPane.showMessageDialog(this,
                        "Zoo has no animals!",
                        "Info", JOptionPane.INFORMATION_MESSAGE);
                return;
            }

            // Use JOptionPane to display animal list instead of JTextArea
            StringBuilder sb = new StringBuilder(zooName + "'s Animal List:\n");
            for (Animal animal : animals) {
                sb.append("Name: ").append(animal.getName())
                        .append(" | Type: ").append(animal.getType())
                        .append(" | Age: ").append(animal.getAge()).append("\n");
            }
            JOptionPane.showMessageDialog(this, sb.toString(), "Animal List", JOptionPane.INFORMATION_MESSAGE);
        });

        // Search animal components
        JPanel searchPanel = new JPanel(new FlowLayout());
        JTextField searchNameField = new JTextField(10);
        JButton searchBtn = new JButton("Search Animal");
        searchBtn.addActionListener(e -> {
            String zooName = (String) zooNameSearchField.getSelectedItem();
            String animalName = searchNameField.getText().trim();
            int index = zooManager.findAnimal(zooName, animalName);
            String message = (index == -1)
                    ? "Animal " + animalName + " not found"
                    : "Animal " + animalName + " found at position " + (index + 1);
            JOptionPane.showMessageDialog(this, message, "Search Result", JOptionPane.INFORMATION_MESSAGE);
        });

        // Ticket sales panel
        JPanel ticketSalesPanel = new JPanel(new FlowLayout());
        ticketSalesPanel.setBorder(BorderFactory.createTitledBorder("Ticket Sales"));
        JTextField ticketQuantityField = new JTextField(5);
        JTextField bankAccountField = new JTextField(10);
        JButton sellTicketsBtn = new JButton("Sell Tickets");

        sellTicketsBtn.addActionListener(e -> {
            try {
                String bankAccount = bankAccountField.getText().trim();
                int quantity = Integer.parseInt(ticketQuantityField.getText().trim());
                double price = 25.0;
                double totalSales = quantity * price;

                boolean withdrawSuccess = bankingService.withdraw(bankAccount.toLowerCase(), totalSales);
                boolean depositSuccess = bankingService.deposit((String)zooNameTicketField.getSelectedItem(), totalSales);

                if(withdrawSuccess && depositSuccess) {
                    JOptionPane.showMessageDialog(this,
                            "Sold " + quantity + " tickets for " + bankAccount + "\nTotal: RMB " + totalSales,
                            "Ticket Sale Success",
                            JOptionPane.INFORMATION_MESSAGE);

                    ticketQuantityField.setText("");
                }
                else {
                    JOptionPane.showMessageDialog(this, "Withdrawal failed (account not found or insufficient balance)", "Error", JOptionPane.ERROR_MESSAGE);}
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(this, "Invalid quantity/price format", "Error", JOptionPane.ERROR_MESSAGE);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Ticket Sale Failed: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        // Assemble view panel components
        listPanel.add(new JLabel("Zoo:"));
        listPanel.add(zooNameListField);
        listPanel.add(listBtn);

        searchPanel.add(new JLabel("Zoo:"));
        searchPanel.add(zooNameSearchField);
        searchPanel.add(new JLabel("Animal Name:"));
        searchPanel.add(searchNameField);
        searchPanel.add(searchBtn);

        ticketSalesPanel.add(new JLabel("Bank Account:"));
        ticketSalesPanel.add(bankAccountField);
        ticketSalesPanel.add(new JLabel("Zoo:"));
        ticketSalesPanel.add(zooNameTicketField);
        ticketSalesPanel.add(new JLabel("Quantity:"));
        ticketSalesPanel.add(ticketQuantityField);
        ticketSalesPanel.add(new JLabel("Price (RMB): 25.0"));
        ticketSalesPanel.add(sellTicketsBtn);

        viewPanel.add(listPanel, BorderLayout.NORTH);
        viewPanel.add(searchPanel, BorderLayout.CENTER);
        viewPanel.add(ticketSalesPanel, BorderLayout.SOUTH);

        // Main panel layout
        zooPanel.add(addAnimalPanel, BorderLayout.NORTH);
        zooPanel.add(operationPanel, BorderLayout.CENTER);
        zooPanel.add(viewPanel, BorderLayout.SOUTH);

        return zooPanel;
    }

    // RestaurantManagement Panel
    private JPanel createRestaurantPanel() {
        RestaurantService.addIngredient("Tomato", 0.75);
        RestaurantService.addIngredient("Lettuce", 0.50);
        RestaurantService.addIngredient("Cheese", 1.25);
        RestaurantService.addIngredient("Beef Patty", 3.50);
        RestaurantService.addIngredient("Chicken Breast", 2.75);
        RestaurantService.addIngredient("Bun", 0.80);
        RestaurantService.addIngredient("French Fries", 1.50);
        RestaurantService.addIngredient("Rice", 1.00);
        RestaurantService.addIngredient("Pasta", 1.20);
        RestaurantService.addIngredient("Marinara Sauce", 1.75);

        JPanel restaurantPanel = new JPanel(new BorderLayout(10, 10));
        restaurantPanel.setBorder(BorderFactory.createTitledBorder("Restaurant Management"));

        // 1. Add Ingredient Panel
        JPanel addIngredientPanel = new JPanel(new FlowLayout());
        addIngredientPanel.setBorder(BorderFactory.createTitledBorder("Add Ingredient"));

        JTextField ingredientNameField = new JTextField(10);
        JTextField ingredientPriceField = new JTextField(5);
        JButton addIngredientBtn = new JButton("Add Ingredient");
        JButton showAllIngredientsBtn = new JButton("Show All Ingredients");

        addIngredientBtn.addActionListener(e -> {
            try {
                String name = ingredientNameField.getText().trim();
                double price = Double.parseDouble(ingredientPriceField.getText().trim());

                RestaurantService.addIngredient(name, price);
                JOptionPane.showMessageDialog(this,
                        "Ingredient Added:\nName: " + name + "\nPrice: RMB " + price,
                        "Success", JOptionPane.INFORMATION_MESSAGE);

                // Clear input fields after success
                ingredientNameField.setText("");
                ingredientPriceField.setText("");
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(this,
                        "Invalid price format (must be a number)",
                        "Error", JOptionPane.ERROR_MESSAGE);
            } catch (IllegalArgumentException ex) {
                JOptionPane.showMessageDialog(this,
                        "Add Failed: " + ex.getMessage(),
                        "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        showAllIngredientsBtn.addActionListener(e -> {
            String ingredientsList = RestaurantService.getAllIngredients();
            JOptionPane.showMessageDialog(this,
                    "All Ingredients:\n" + ingredientsList,
                    "Ingredients List", JOptionPane.INFORMATION_MESSAGE);
        });

        addIngredientPanel.add(new JLabel("Ingredient Name:"));
        addIngredientPanel.add(ingredientNameField);
        addIngredientPanel.add(new JLabel("Price:"));
        addIngredientPanel.add(ingredientPriceField);
        addIngredientPanel.add(addIngredientBtn);
        addIngredientPanel.add(showAllIngredientsBtn);

        // 2. Meal Management Panel
        JPanel mealManagementPanel = new JPanel();
        mealManagementPanel.setLayout(new BoxLayout(mealManagementPanel, BoxLayout.Y_AXIS));

        // 2.1 Create Meal Sub-panel
        JPanel createMealPanel = new JPanel(new FlowLayout());
        createMealPanel.setBorder(BorderFactory.createTitledBorder("Create Meal"));

        JTextField mealNameField = new JTextField(10);
        JTextField ingredientsField = new JTextField(20);  // Format: "ing1,ing2,ing3"
        JButton createMealBtn = new JButton("Create Meal");

        createMealBtn.addActionListener(e -> {
            try {
                String mealName = mealNameField.getText().trim();
                String[] ingredientNames = ingredientsField.getText().trim().split(",");
                ArrayList<String> ingredients = new ArrayList<>(List.of(ingredientNames));

                RestaurantService.createMeal(mealName, ingredients);
                JOptionPane.showMessageDialog(this,
                        "Meal Created:\nName: " + mealName + "\nIngredients: " + String.join(", ", ingredients),
                        "Success", JOptionPane.INFORMATION_MESSAGE);

                // Clear input fields
                mealNameField.setText("");
                ingredientsField.setText("");
            } catch (IllegalArgumentException ex) {
                JOptionPane.showMessageDialog(this,
                        "Create Failed: " + ex.getMessage(),
                        "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        createMealPanel.add(new JLabel("Meal Name:"));
        createMealPanel.add(mealNameField);
        createMealPanel.add(new JLabel("Ingredients (comma-separated):"));
        createMealPanel.add(ingredientsField);
        createMealPanel.add(createMealBtn);

        // 2.2 Remove Meal Sub-panel
        JPanel removeMealPanel = new JPanel(new FlowLayout());
        removeMealPanel.setBorder(BorderFactory.createTitledBorder("Remove Meal"));

        JTextField removeMealNameField = new JTextField(10);
        JButton removeMealBtn = new JButton("Remove Meal");

        removeMealBtn.addActionListener(e -> {
            String mealName = removeMealNameField.getText().trim();
            if (mealName.isEmpty()) {
                JOptionPane.showMessageDialog(this, "Please enter meal name!", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            boolean success = RestaurantService.removeMeal(mealName);
            if (success) {
                JOptionPane.showMessageDialog(this, "Meal '" + mealName + "' removed successfully!", "Success", JOptionPane.INFORMATION_MESSAGE);
            } else {
                JOptionPane.showMessageDialog(this, "Meal '" + mealName + "' not found in menu!", "Error", JOptionPane.ERROR_MESSAGE);
            }
            removeMealNameField.setText("");  // Clear input field
        });

        removeMealPanel.add(new JLabel("Meal Name:"));
        removeMealPanel.add(removeMealNameField);
        removeMealPanel.add(removeMealBtn);

        // Add sub-panels to meal management panel
        mealManagementPanel.add(createMealPanel);
        mealManagementPanel.add(removeMealPanel);

        // 3. Order Management Panel
        JPanel orderManagementPanel = new JPanel(new BorderLayout());
        orderManagementPanel.setBorder(BorderFactory.createTitledBorder("Order Management"));

        // 3.1 Place Order Sub-panel
        JPanel placeOrderPanel = new JPanel(new FlowLayout());
        JTextField orderMealField = new JTextField(10);
        JTextField orderQuantityField = new JTextField(5);
        JButton addToOrderBtn = new JButton("Add to Order");
        JButton placeOrderBtn = new JButton("Place Order");
        JTextField customerIdField = new JTextField(10);  // Bank account for payment

        // Temporary order storage
        HashMap<String, Integer> currentOrder = new HashMap<>();

        // Add to Order Button Logic
        addToOrderBtn.addActionListener(e -> {
            try {
                String mealName = orderMealField.getText().trim();
                int quantity = Integer.parseInt(orderQuantityField.getText().trim());

                // Input validation
                if (mealName.isEmpty()) {
                    JOptionPane.showMessageDialog(this, "Meal name cannot be empty!", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }
                if (quantity <= 0) {
                    JOptionPane.showMessageDialog(this, "Quantity must be positive!", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                // Check if meal exists
                if (!RestaurantService.findMealByName(mealName)) {
                    JOptionPane.showMessageDialog(this, "Meal '" + mealName + "' not found in menu!", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                // Update temporary order
                currentOrder.put(mealName, currentOrder.getOrDefault(mealName, 0) + quantity);
                JOptionPane.showMessageDialog(this,
                        "Added to Order:\nMeal: " + mealName + "\nQuantity: " + quantity,
                        "Success", JOptionPane.INFORMATION_MESSAGE);

                // Clear input fields
                orderMealField.setText("");
                orderQuantityField.setText("");
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(this,
                        "Invalid quantity format (must be an integer)",
                        "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        // Place Order Button Logic
        placeOrderBtn.addActionListener(e -> {
            if (currentOrder.isEmpty()) {
                JOptionPane.showMessageDialog(this, "Order cannot be empty", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            String customerId = customerIdField.getText().trim();
            if (customerId.isEmpty()) {
                JOptionPane.showMessageDialog(this, "Customer ID cannot be empty", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            try {
                // Calculate total amount
                String orderId = RestaurantService.placeOrder(currentOrder);
                double total = RestaurantService.calculateBill(orderId);

                // Verify and deduct from bank account
                boolean withdrawSuccess = bankingService.withdraw(customerId, total);
                if (withdrawSuccess) {
                    JOptionPane.showMessageDialog(this,
                            "Order placed successfully!\nOrder ID: " + orderId + "\nTotal: RMB" + total + "\nDeducted from customer account.",
                            "Success",
                            JOptionPane.INFORMATION_MESSAGE);
                    // Clear order and input fields
                    currentOrder.clear();
                    customerIdField.setText("");
                } else {
                    JOptionPane.showMessageDialog(this, "Withdrawal failed (account not found or insufficient balance)", "Error", JOptionPane.ERROR_MESSAGE);
                }
            } catch (IllegalArgumentException ex) {
                JOptionPane.showMessageDialog(this, "Place order failed: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        // Assemble place order panel components
        placeOrderPanel.add(new JLabel("Meal Name:"));
        placeOrderPanel.add(orderMealField);
        placeOrderPanel.add(new JLabel("Quantity:"));
        placeOrderPanel.add(orderQuantityField);
        placeOrderPanel.add(addToOrderBtn);
        placeOrderPanel.add(new JLabel("Bank Account:"));
        placeOrderPanel.add(customerIdField);
        placeOrderPanel.add(placeOrderBtn);

        // 3.2 Calculate Bill Sub-panel (independent)
        JPanel calculateBillPanel = new JPanel(new FlowLayout());
        JTextField orderIdField = new JTextField(15);
        JButton calculateBillBtn = new JButton("Calculate Bill");

        calculateBillBtn.addActionListener(e -> {
            String orderId = orderIdField.getText().trim();
            if (orderId.isEmpty()) {
                JOptionPane.showMessageDialog(this, "Order ID cannot be empty", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            if (!orderId.startsWith("ORD-")) {
                JOptionPane.showMessageDialog(this, "Invalid Order ID format. Must start with 'ORD-'", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            try {
                String timestampStr = orderId.substring(4);
                Long.parseLong(timestampStr);
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(this, "Invalid Order ID. Timestamp part must be a valid number", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            try {
                double total = RestaurantService.calculateBill(orderId);
                JOptionPane.showMessageDialog(this,
                        "Order Total: RMB " + String.format("%.2f", total),
                        "Bill Calculated", JOptionPane.INFORMATION_MESSAGE);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Calculate Failed: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        calculateBillPanel.add(new JLabel("Order ID:"));
        calculateBillPanel.add(orderIdField);
        calculateBillPanel.add(calculateBillBtn);

        // Assemble order management panel
        orderManagementPanel.add(placeOrderPanel, BorderLayout.NORTH);
        orderManagementPanel.add(calculateBillPanel, BorderLayout.CENTER);

        // Main panel layout
        restaurantPanel.add(addIngredientPanel, BorderLayout.NORTH);
        restaurantPanel.add(mealManagementPanel, BorderLayout.CENTER);
        restaurantPanel.add(orderManagementPanel, BorderLayout.SOUTH);

        return restaurantPanel;
    }

    // Banking Management Module Panel
    private JPanel createBankPanel() {
        JPanel bankPanel = new JPanel(new BorderLayout(10, 10));
        bankPanel.setBorder(BorderFactory.createTitledBorder("Banking Management"));

        // 1. Account Creation Panel
        JPanel accountCreationPanel = new JPanel(new FlowLayout());
        accountCreationPanel.setBorder(BorderFactory.createTitledBorder("Create Bank Account"));

        // Account Number Input
        JLabel accountNumberLabel = new JLabel("Account Number:");
        accountNumberField = new JTextField(10);
        accountCreationPanel.add(accountNumberLabel);
        accountCreationPanel.add(accountNumberField);

        // Initial Balance Input
        JLabel initialBalanceLabel = new JLabel("Initial Balance:");
        initialBalanceField = new JTextField(10);
        accountCreationPanel.add(initialBalanceLabel);
        accountCreationPanel.add(initialBalanceField);

        // Interest Rate Input
        JLabel interestRateLabel = new JLabel("Annual Interest Rate (%):");
        interestRateField = new JTextField(5);
        accountCreationPanel.add(interestRateLabel);
        accountCreationPanel.add(interestRateField);

        // Create Account Button
        JButton createAccountBtn = new JButton("Create Account");
        createAccountBtn.addActionListener(e -> createAccount());
        accountCreationPanel.add(createAccountBtn);

        // 2. Transaction Panel
        JPanel transactionPanel = new JPanel(new FlowLayout());
        transactionPanel.setBorder(BorderFactory.createTitledBorder("Banking Transactions"));

        // Account Number Input
        JLabel transactionAccountLabel = new JLabel("Account Number:");
        transactionAccountField = new JTextField(10);
        transactionPanel.add(transactionAccountLabel);
        transactionPanel.add(transactionAccountField);

        // Transaction Amount Input
        JLabel transactionAmountLabel = new JLabel("Amount:");
        transactionAmountField = new JTextField(10);
        transactionPanel.add(transactionAmountLabel);
        transactionPanel.add(transactionAmountField);

        // Transaction Type Selection
        String[] transactionTypes = {"Deposit", "Withdraw"};
        transactionTypeCombo = new JComboBox<>(transactionTypes);
        transactionPanel.add(transactionTypeCombo);

        // Process Transaction Button
        JButton processTransactionBtn = new JButton("Process Transaction");
        processTransactionBtn.addActionListener(e -> processTransaction());
        transactionPanel.add(processTransactionBtn);

        // 3. Task Management Panel
        JPanel taskManagementPanel = new JPanel(new BorderLayout());
        taskManagementPanel.setBorder(BorderFactory.createTitledBorder("Task Management"));

        // Task Input Sub-panel
        JPanel taskInputPanel = new JPanel(new FlowLayout());
        JLabel taskInputLabel = new JLabel("Task:");
        taskInputField = new JTextField(20);
        JButton addTaskBtn = new JButton("Add Task");
        addTaskBtn.addActionListener(e -> addTask());
        taskInputPanel.add(taskInputLabel);
        taskInputPanel.add(taskInputField);
        taskInputPanel.add(addTaskBtn);

        // Task Lists Sub-panel
        highPriorityModel = new DefaultListModel<>();
        lowPriorityModel = new DefaultListModel<>();
        highPriorityList = new JList<>(highPriorityModel);
        lowPriorityList = new JList<>(lowPriorityModel);

        JPanel taskListPanel = new JPanel(new GridLayout(1, 2));
        taskListPanel.add(new JScrollPane(highPriorityList));
        taskListPanel.add(new JScrollPane(lowPriorityList));

        // Task Action Buttons Sub-panel
        JPanel taskActionPanel = new JPanel(new FlowLayout());
        JButton removeTaskBtn = new JButton("Remove Task");
        removeTaskBtn.addActionListener(e -> removeTask());
        JButton changePriorityBtn = new JButton("Change Priority");
        changePriorityBtn.addActionListener(e -> changePriority());  // Key button for priority switching
        taskActionPanel.add(removeTaskBtn);
        taskActionPanel.add(changePriorityBtn);

        // Assemble Task Management Panel
        taskManagementPanel.add(taskInputPanel, BorderLayout.NORTH);
        taskManagementPanel.add(taskListPanel, BorderLayout.CENTER);
        taskManagementPanel.add(taskActionPanel, BorderLayout.SOUTH);

        // Assemble Main Banking Panel
        bankPanel.add(accountCreationPanel, BorderLayout.NORTH);
        bankPanel.add(transactionPanel, BorderLayout.CENTER);
        bankPanel.add(taskManagementPanel, BorderLayout.SOUTH);

        return bankPanel;
    }

    private void createAccount() {
        try {
            String accountNumber = accountNumberField.getText().trim();
            double initialBalance = Double.parseDouble(initialBalanceField.getText().trim());
            double interestRate = Double.parseDouble(interestRateField.getText().trim()) / 100;

            // Create account
            bankingService.createAccount(accountNumber, initialBalance);

            // Show success message
            JOptionPane.showMessageDialog(this,
                    "Account Created:\n" +
                            "Number: " + accountNumber + "\n" +
                            "Initial Balance: " + currencyFormat.format(initialBalance) + "\n" +
                            "Interest Rate: " + (interestRate * 100) + "%",
                    "Account Creation Successful",
                    JOptionPane.INFORMATION_MESSAGE);

            // Clear input fields
            accountNumberField.setText("");
            initialBalanceField.setText("");
            interestRateField.setText("");
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(this,
                    "Please enter valid numbers for balance and interest rate.",
                    "Invalid Input",
                    JOptionPane.ERROR_MESSAGE);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this,
                    "Error creating account: " + ex.getMessage(),
                    "Account Creation Error",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    private void processTransaction() {
        try {
            String accountNumber = transactionAccountField.getText().trim();
            double amount = Double.parseDouble(transactionAmountField.getText().trim());
            String transactionType = (String) transactionTypeCombo.getSelectedItem();
            boolean transactionSuccess = false;

            // Execute transaction based on type
            if ("Deposit".equals(transactionType)) {
                transactionSuccess = bankingService.deposit(accountNumber, amount);
            } else {
                transactionSuccess = bankingService.withdraw(accountNumber, amount);
            }

            // Show success or failure message
            if (transactionSuccess) {
                JOptionPane.showMessageDialog(this,
                        transactionType + " of " + currencyFormat.format(amount) +
                                " to " + accountNumber + " successful!",
                        "Transaction Success",
                        JOptionPane.INFORMATION_MESSAGE);
                // Clean up input fields after success
                transactionAccountField.setText("");
                transactionAmountField.setText("");
            } else {
                // Failed transaction message
                String errorMsg = "Deposit" .equals(transactionType) ?
                        "Deposit failed: Account not found" :
                        "Withdraw failed: Insufficient balance or account not found";
                JOptionPane.showMessageDialog(this,
                        errorMsg,
                        "Transaction Error",
                        JOptionPane.ERROR_MESSAGE);
            }
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(this,
                    "Please enter a valid transaction amount.",
                    "Invalid Input",
                    JOptionPane.ERROR_MESSAGE);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this,
                    "Transaction failed: " + ex.getMessage(),
                    "Transaction Error",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    private void updateTaskLists() {
        highPriorityModel.clear();
        lowPriorityModel.clear();

        for (String task : bankingService.listHighPriorityTasks()) {
            highPriorityModel.addElement(task);
        }

        for (String task : bankingService.listLowPriorityTasks()) {
            lowPriorityModel.addElement(task);
        }
    }

    private void addTask() {
        String task = taskInputField.getText().trim();
        if (!task.isEmpty()) {
            bankingService.addTask(task);
            updateTaskLists();
            taskInputField.setText("");
        }
    }

    private void removeTask() {
        if (!highPriorityList.isSelectionEmpty()) {
            int index = highPriorityList.getSelectedIndex();
            bankingService.removeTask("high", index);
        } else if (!lowPriorityList.isSelectionEmpty()) {
            int index = lowPriorityList.getSelectedIndex();
            bankingService.removeTask("low", index);
        }
        updateTaskLists();
    }

    private void changePriority() {
        if (!highPriorityList.isSelectionEmpty()) {
            int index = highPriorityList.getSelectedIndex();
            bankingService.changePriority("high", index);
        } else if (!lowPriorityList.isSelectionEmpty()) {
            int index = lowPriorityList.getSelectedIndex();
            bankingService.changePriority("low", index);
        }
        updateTaskLists();
    }

    // ShapeService Panel
    private JPanel createShapePanel() {
        JPanel shapePanel = new JPanel(new BorderLayout(10, 10));
        shapePanel.setBorder(BorderFactory.createTitledBorder("Shape Service"));

        // 1. File input & parsing panel
        JPanel filePanel = new JPanel(new FlowLayout());
        filePanel.setBorder(BorderFactory.createTitledBorder("File Management"));

        JTextField filePathField = new JTextField(25);  // Input field for file path
        JButton fileSelectBtn = new JButton("Select File");
        JButton parseBtn = new JButton("Parse File");

        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileChooser.setAcceptAllFileFilterUsed(false);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Text Files (*.txt, *.TXT)", "txt","TXT");
        fileChooser.addChoosableFileFilter(filter);
        fileChooser.setDialogTitle("Choose File");

        fileSelectBtn.addActionListener(e -> {
            int value = fileChooser.showDialog(this, "Select File");
            if (value == JFileChooser.APPROVE_OPTION) {
                File selectedFile = fileChooser.getSelectedFile();
                filePathField.setText(selectedFile.getAbsolutePath());
            }
        });

        parseBtn.addActionListener(e -> {
            try {
                String filePath = filePathField.getText().trim();
                if (filePath.isEmpty()) {
                    JOptionPane.showMessageDialog(this, "File path cannot be empty!", "Error", JOptionPane.ERROR_MESSAGE);
                    return;
                }

                // Call ShapeService API to parse file
                currentShapes = ShapeService.parseFile(filePath);
                JOptionPane.showMessageDialog(this,
                        "Parsed " + currentShapes.size() + " shapes successfully!",
                        "Success", JOptionPane.INFORMATION_MESSAGE);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(this,
                        "Parse failed: " + ex.getMessage(),
                        "Error", JOptionPane.ERROR_MESSAGE);
            }
        });

        filePanel.add(new JLabel("File Path:"));
        filePanel.add(filePathField);
        filePanel.add(fileSelectBtn);
        filePanel.add(parseBtn);

        // 2. Statistics display panel
        JPanel statsPanel = new JPanel(new BorderLayout());
        statsPanel.setBorder(BorderFactory.createTitledBorder("Shape Statistics"));

        JTextArea resultArea = new JTextArea(10, 30);
        resultArea.setEditable(false);
        JScrollPane resultScroll = new JScrollPane(resultArea);

        JButton countBtn = new JButton("Count Shapes by Type");
        countBtn.addActionListener(e -> {
            if (currentShapes == null || currentShapes.isEmpty()) {
                JOptionPane.showMessageDialog(this, "No shapes parsed yet!", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            // Call ShapeService API to count shapes
            HashMap<String, Integer> countMap = ShapeService.countByType(currentShapes);

            // Format statistics result
            StringBuilder sb = new StringBuilder("Shape Type Counts:\n");
            for (String type : countMap.keySet()) {
                sb.append(type).append(": ").append(countMap.get(type)).append("\n");
            }
            resultArea.setText(sb.toString());
        });

        statsPanel.add(countBtn, BorderLayout.NORTH);
        statsPanel.add(resultScroll, BorderLayout.CENTER);

        // 3. Bounce box display panel
        JPanel bounceBoxPanel = new JPanel(new BorderLayout());
        bounceBoxPanel.setBorder(BorderFactory.createTitledBorder("Bounce Box"));
        JButton bounceBtn = new JButton("Bounce Shapes");
        bounceBtn.addActionListener(e -> {
            if (currentShapes == null || currentShapes.isEmpty()) {
                JOptionPane.showMessageDialog(this, "No shapes parsed yet!", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            shapeService.displayShapes(currentShapes);
        });
        bounceBoxPanel.add(bounceBtn, BorderLayout.NORTH);

        // Assemble main panel
        shapePanel.add(filePanel, BorderLayout.NORTH);
        shapePanel.add(statsPanel, BorderLayout.CENTER);
        shapePanel.add(bounceBoxPanel, BorderLayout.SOUTH);


// PROCESS MODULE PART
        // Visualize Animal Counts Button
        JButton visualizeAnimalCountsBtn = new JButton("Show Animal Count Chart");
        visualizeAnimalCountsBtn.addActionListener(e -> {
            ArrayList<Shape> chartShapes = new ArrayList<>();

            // Get all names of zoos
            String[] zooNames = {"SouthZoo", "NorthZoo"};
            int x = 50;
            int baseY = 300;
            int barWidth = 40;

            for (String zooName : zooNames) {
                int animalCount = zooManager.listAnimals(zooName).size();
                int barHeight = animalCount * 20;

                Rectangle bar = new Rectangle(x, baseY - barHeight, barWidth, barHeight);
                bar.setColor(Color.BLUE);
                chartShapes.add(bar);

                int labelX = x + barWidth / 2 - 5;
                int labelY = baseY + 10;
                Square label = new Square(labelX, labelY, 10);
                label.setColor(Color.RED);
                chartShapes.add(label);

                x += barWidth + 20;
            }

            // Use ShapeService to display the shapes
            shapeService.displayShapes(chartShapes);
        });

        // Put the button in the center of the bounce box panel
        bounceBoxPanel.add(visualizeAnimalCountsBtn, BorderLayout.CENTER);  // Change the position to CENTER
        return shapePanel;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new IMS_Swing_Dashboard().setVisible(true));
    }
}